﻿using adb;
using EntityFrameworkCore.UseRowNumberForPaging;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Notication.AppCode;
using System;
using System.Data.Common;
using System.Text.Json;
using Z.EntityFramework.Extensions;

namespace Notication
{

    /// <summary>
    /// 
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            this.ConfigZLib();
            StatisticsRun.t = DateTime.Now;
        }
        /// <summary>
        /// 配置数据库日志
        /// </summary>
        public void ConfigZLib()
        {
            Action<DbCommand> action = cmd => {
                Console.Write("语句开始:");
                Console.Write(System.Environment.NewLine);
                for (var i = 0; i < cmd.Parameters.Count; i++)
                {
                    var item = cmd.Parameters[i];
                    Console.WriteLine($"{item.ParameterName} = {item.Value},${item.DbType}");
                }
                Console.Write(System.Environment.NewLine);
                Console.Write(cmd.CommandText);
                Console.Write(System.Environment.NewLine);
                Console.Write("语句结束");
                Console.Write(System.Environment.NewLine);
            };
            BatchUpdateManager.BatchUpdateBuilder = builder => {
                builder.Executing = action;
            };
            BatchDeleteManager.BatchDeleteBuilder = builder =>
            {
                builder.Executing = action;
            };
        }
        /// <summary>
        /// 
        /// </summary>
        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<FormOptions>(options =>
            {
                options.ValueLengthLimit = int.MaxValue;
                options.MultipartBodyLengthLimit = long.MaxValue; // <-- ! long.MaxValue
                options.MultipartBoundaryLengthLimit = int.MaxValue;
                options.MultipartHeadersCountLimit = int.MaxValue;
                options.MultipartHeadersLengthLimit = int.MaxValue;
               
            });
            services.AddDbContext<MyDbContext>(optionsBuilder =>
            {
                object p = optionsBuilder.UseSqlServer(this.Configuration["DBStr"], b => b.UseRowNumberForPaging());
                //optionsBuilder.LogTo(x =>
                //{
                //    Console.WriteLine(x);
                //}, LogLevel.Information);
                optionsBuilder.EnableSensitiveDataLogging(true);
            });
            services.AddDbContext<DeviceDbContext>(optionsBuilder =>
            {
                object p = optionsBuilder.UseSqlServer(this.Configuration["DBDeviceStr"], b => b.UseRowNumberForPaging());
                //optionsBuilder.LogTo(x =>
                //{
                //    Console.WriteLine(x);
                //}, LogLevel.Information);
                optionsBuilder.EnableSensitiveDataLogging(true);
            });
            services.AddDbContext<LogDbContext>(optionsBuilder =>
            {
                object p = optionsBuilder.UseSqlServer(this.Configuration["LogStr"], b => b.UseRowNumberForPaging());
                //optionsBuilder.LogTo(x =>
                //{
                //    Console.WriteLine(x);
                //}, LogLevel.Information);
                optionsBuilder.EnableSensitiveDataLogging(true);
            });
            services.AddControllers().AddJsonOptions(options => {
                options.JsonSerializerOptions.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
            });

            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddCors(options =>
            {
                options.AddPolicy("Test",
                builder => builder.AllowAnyOrigin()
                .WithMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS")
                .WithHeaders("authorization", "content-type")
                );
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseCalculateExecutionTime();
            if (false)//(env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(errorApp =>
                {
                    errorApp.Run(async context =>
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "application/json";
                        var ex = context.Features.Get<IExceptionHandlerPathFeature>();
                        await context.Response.WriteAsync(JsonSerializer.Serialize(ResultApi.error<object>(null, ex?.Error.Message)));
                    });
                });
                app.UseHsts();
            }
            app.UseCors("Test");
            app.UseHttpsRedirection();
            app.Use((context, next) =>
            {
                context.Request.EnableBuffering();
                return next();
            });
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

    }
}
